#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using UTable.Input;
using UTable.Input.MultiTouch;
using UTable.Objects.Handlers;

namespace UTable.Objects.Controls
{
    public class UElementMenuItem : HeaderedItemsControl, IControl
    {
        #region Dependency Properties

        // Using a DependencyProperty as the backing store for Icon.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(object), typeof(UElementMenuItem), new UIPropertyMetadata(null));


        // Using a DependencyProperty as the backing store for IsActive.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsActiveProperty =
            DependencyProperty.Register("IsActive", typeof(bool), typeof(UElementMenuItem), new UIPropertyMetadata(true));


        // Using a DependencyProperty as the backing store for IsPressed.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsPressedProperty =
            DependencyProperty.Register("IsPressed", typeof(bool), typeof(UElementMenuItem), new UIPropertyMetadata(false));

        #endregion        

        #region Private Methods

        private UElementMenu _menuRoot;

        private UElementMenuDirectory _parent;

        private UElementMenuPanel _panel;

        private int _activeItemIndex = -1;

        internal Path line;

        internal LineSegment lineSegment;

        internal PathFigure pathFigure;

        #endregion

        #region Constructors

        static UElementMenuItem()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(UElementMenuItem), new FrameworkPropertyMetadata(typeof(UElementMenuItem)));
            UControlImpl.OverrideMetadata(typeof(UElementMenuItem));
        }

        public UElementMenuItem()
        {
            InitializeIControlPart();

            DetectContactsHandler handler = new DetectContactsHandler();
            handler.NewContact += new ContactEventHandler(OnNewContact);
            handler.NoContact += new ContactEventHandler(OnNoContact);
            MultiTouchProcessor.Handlers.Add(handler);
            this.InputReceived += UButton_InputReceived;
            this.Role = UElementMenuItemRole.Item;
        }

        #endregion

        #region Private Methods

        private void OnMultiTouchDetected(MultiTouchEventArgs args)
        {
            foreach (FingerEventArgs f in args.FingerEvents)
            {
                if (f.EventType == FingerEventType.FINGER_DOWN_EVENT || f.EventType == FingerEventType.FINGER_IN_EVENT)
                {
                    this.MenuRoot.OnFingerDownOnMenu(f.FingerID);
                }
                if (f.EventType == FingerEventType.FINGER_UP_EVENT)
                {
                    this.MenuRoot.OnFingerUpOnMenu(f.FingerID);
                }
            }
        }

        protected virtual void OnNoContact(FingerEventArgs args)
        {
            Point p = args.Position;
            this.IsPressed = false;
            if (args.EventType == FingerEventType.FINGER_UP_EVENT && p.X >= 0 && p.X <= this.ActualWidth && p.Y >= 0 && p.Y <= this.ActualHeight)
            {
                if (this.Role == UElementMenuItemRole.Item)
                {
                    // Execute the command, and hide the entire tree
                    OnClick();
                    if (this.Click != null)
                        this.Click(this, null);
                    this.MenuRoot.RaiseCommandReceivedEvent(new ElementMenuCommandReceivedEventArgs(this.Command, this));
                    this.MenuRoot.CloseSubmenu(true);
                }
            }
        }

        protected virtual void OnNewContact(FingerEventArgs args)
        {
            this.IsPressed = true;
        }

        private void UButton_InputReceived(InputEventArgs args)
        {
            if (!this.IsEnabled)
                return;
            
            if (args is MultiTouchEventArgs)
                OnMultiTouchDetected(args as MultiTouchEventArgs);
            args.Handled = true;
			args.RouteDown = false;
        }

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			// create line
			line = this.GetTemplateChild("PART_Line") as Path;
			lineSegment = new LineSegment();
			pathFigure = new PathFigure();
			pathFigure.Segments.Add(lineSegment);
			PathFigureCollection figureCollection = new PathFigureCollection();
			figureCollection.Add(pathFigure);
			line.Data = new PathGeometry(figureCollection);
		}

        #endregion

        #region Properties
        //
        // Summary:
        //     Gets or sets the icon of the menu item.
        //
        // Remarks:
        //     The Icon property is a dependency property that is identified by the UTable.Objects.Controls.ElementMenuItem.IconProperty
        //     field.
        public object Icon
        {
            get { return (object)GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }
        //
        // Summary:
        //     Gets a value that indicates whether this menu item is visible.
        //
        // Remarks:
        //      The IsActive property is a dependency property that is identified by the
        //     UTable.Objects.Controls.ElementMenuItem.IsActiveProperty
        //     field.
        //     In contrast to the System.Windows.UIElement.Visibility property, IsActive
        //     enables menu items to fade in and out instead of instantly showing or hiding.
        //     To override the default fade animations, you can trigger off the IsActive
        //     property in your own ElementMenuItem styles.
        public bool IsActive
        {
            get { return (bool)GetValue(IsActiveProperty); }
            internal set { SetValue(IsActiveProperty, value); }
        }
        //
        // Summary:
        //     Gets a value that indicates whether this menu item is pressed.
        //
        // Remarks:
        //     The IsPressed property is a dependency property that is identified by the
        //     UTable.Objects.Controls.ElementMenuItem.IsPressedProperty
        //     field.
        public bool IsPressed
        {
            get { return (bool)GetValue(IsPressedProperty); }
            internal set { SetValue(IsPressedProperty, value); }
        }

        //
        // Summary:
        //     Gets the root UTable.Objects.Controls.ElementMenu object
        //     that contains this UTable.Objects.Controls.ElementMenuItem
        //     object.
        public UElementMenu MenuRoot
        {
            get { return _menuRoot; }
            internal set { _menuRoot = value; }
        }

        public UElementMenuDirectory ParentMenuItem
        {
            get { return _parent; }
            internal set { _parent = value; }
        }

        public String Command { get; set; }

        //
        // Summary:
        //     Gets the role of the menu item.
        //
        // Remarks:
        //     The Role property is a dependency property that is identified by the UTable.Objects.Controls.ElementMenuItem.RoleProperty
        //     field.
        public UElementMenuItemRole Role
        {
            get;
            internal set;
        }

        #endregion

        #region Events

        // Summary:
        //     Occurs when a contact is released on an executable item.
        //
        // Remarks:
        //     The Click event is a routed event that is identified by the UTable.Objects.Controls.ElementMenuItem.ClickEvent
        //     field.
        public event EventHandler Click;

        #endregion

        #region Methods

        //
        // Summary:
        //     An ElementMenuItem is clicked, raising a UTable.Objects.Controls.ElementMenuItem.Click
        //     event.
        //
        // Remarks:
        //     If you override this method, call base.OnClick() to get the default behavior
        //     for an ElementMenuItem object, which should raise a click event, call a command
        //     if there is one, and close the menu.
        protected virtual void OnClick()
        {
            
        }

        #endregion

		#region IControl Implementation
		
		#region Private Fields

        private ControlBaseImpl _impl;

        #endregion

		#region Private Methods

		private void InitializeIControlPart()
        {
			_impl = new ControlBaseImpl(this);
            _impl.GotFingerCapture += new UTable.Input.MultiTouch.FingerEventHandler(_impl_GotFingerCapture);
            _impl.LostFingerCapture += new UTable.Input.MultiTouch.FingerEventHandler(_impl_LostFingerCapture);
			this.InputReceived += new UTable.Input.InputEventHandler(_impl_InputReceived);
        }

        void _impl_InputReceived(UTable.Input.InputEventArgs args)
        {
			if (args is UTable.Input.MultiTouch.MultiTouchEventArgs)
				MultiTouchProcessor.RaiseMultiTouchEvent(args as UTable.Input.MultiTouch.MultiTouchEventArgs);
        }

        void _impl_LostFingerCapture(object sender, UTable.Input.MultiTouch.FingerEventArgs args)
        {
            if (LostFingerCapture != null)
                LostFingerCapture(sender, args);
        }

        void _impl_GotFingerCapture(object sender, UTable.Input.MultiTouch.FingerEventArgs args)
        {
            if (GotFingerCapture != null)
                GotFingerCapture(sender, args);
        }

        #endregion

        #region IControl Members

        public UTable.Objects.Controls.ControlInfo Info
        {
            get { return _impl.Info; }
        }
		
		public UTable.Objects.Handlers.MultiTouchProcessor MultiTouchProcessor 
		{ 
			get { return _impl.MultiTouchProcessor; } 
		}

        #endregion

        #region IVisualNode Members

        public String ID
        {
            get { return _impl.ID; }
        }

        public new double Width
        {
            get { return _impl.Width; }
            set { _impl.Width = value; }
        }

        public new double Height
        {
            get { return _impl.Height; }
            set { _impl.Height = value; }
        }

        public new bool IsHitTestVisible
        {
            get { return _impl.IsHitTestVisible; }
            set { _impl.IsHitTestVisible = value; }
        }

        #endregion

        #region IInputNode Members

        public void RaiseEvent(UTable.Input.InputEventArgs e)
        {
            if (InputReceived != null)
            {
                InputReceived(e);
            }
            OnInputReceived(e);
        }

        public virtual void OnInputReceived(UTable.Input.InputEventArgs args)
        {
            _impl.OnInputReceived(args);
        }

        public bool CaptureFinger(int fingerId)
        {
            return _impl.CaptureFinger(fingerId);
        }

        public bool UncaptureFinger(int fingerId)
        {
            return _impl.UncaptureFinger(fingerId);
        }

        public event UTable.Input.MultiTouch.FingerEventHandler GotFingerCapture;

        public event UTable.Input.MultiTouch.FingerEventHandler LostFingerCapture;

        public event UTable.Input.InputEventHandler InputReceived;

        #endregion
        #endregion
    }
}
